#pragma once

#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>

template <class T>
class RingQueue
{
	private:
		int cap;
		std::vector<T> ring;
		//生产者和消费者必须有自己的下标
		int c_index;
		int p_index;
		pthread_mutex_t c_lock;
		pthread_mutex_t p_lock;
		//单生产，单消费情况下，不需要加锁
		//多生产，多消费由于竞争关系，需要加锁
		sem_t sem_space;
		sem_t sem_data;
	public:
		RingQueue(int _cap):cap(_cap),ring(_cap),c_index(0),p_index(0)
	{
		pthread_mutex_init(&c_lock,nullptr);
		pthread_mutex_init(&p_lock,nullptr);
		sem_init(&sem_space,0,_cap);
		sem_init(&sem_data,0,0);
	}
		int Put(const T& in)
		{
			sem_wait(&sem_space);
			ring[p_index] = in;
			sem_post(&sem_data);
			int ret = p_index;
			p_index++;
			p_index %= cap;
			return ret;
		}
		int Get(T* out)
		{
			sem_wait(&sem_data);
			*out = ring[c_index];
			sem_post(&sem_space);
			int ret = c_index;
			c_index++;
			c_index %= cap;
			return ret;
		}
		~RingQueue()
		{
			pthread_mutex_destroy(&c_lock);
			pthread_mutex_destroy(&p_lock);

			sem_destroy(&sem_space);
			sem_destroy(&sem_data);
		}
};
